home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * CagdOslo.c - an implementation of the oslo algorithm (1). *
- *******************************************************************************
- * Written by Gershon Elber, Aug. 92. *
- ******************************************************************************/
-
- #include <cagd_loc.h>
-
- #define KNOT_INFINITY 1e20
-
- #ifdef DEBUG
- static void PrintAlphaMat(BspKnotAlphaCoeffType *A);
- #endif /* DEBUG */
-
- /******************************************************************************
- * Computes the values of the alpha coefficients, Ai,k(j) of order k: *
- * *
- * n n m m n *
- * _ _ _ _ _ *
- * C(t) = \ Pi Bi,k(t) = \ Pi \ Ai,k(j) Nj,k(t) = \ ( \ Pi Ai,k(j) ) Nj,k(t) *
- * / / / / / *
- * - - - - - *
- * i=0 i=0 j=0 j=0 i=0 *
- * *
- * Let T be the original knot vector and let t be the refined one, i.e. T is *
- * a subset of t. *
- * The Ai,k(j) are computed from the following recursive definition: *
- * *
- * 1, T(i) <= t(i) < T(i+1) *
- * / *
- * Ai,1(j) = *
- * \ *
- * 0, otherwise. *
- * *
- * *
- * T(j+k-1) - T(i) T(i+k) - T(j+k-1) *
- * Ai,k(j) = --------------- Ai,k-1(j) + --------------- Ai+1,k-1(j) *
- * T(i+k-1) - T(i) T(i+k) - T(i+1) *
- * *
- * LengthKVT + k is the length of KVT and similarly LengthKVt + k is the *
- * length of KVt. In other words, LengthKVT and LengthKVt are the control *
- * points len... *
- * *
- * The output matrix has LengthKVT rows and LengthKVt columns (#cols > #rows) *
- * ColIndex/Length hold LengthKVt pairs of first non zero scalar and length of *
- * non zero values in that column, so not all LengthKVT scalars are blended. *
- ******************************************************************************/
- BspKnotAlphaCoeffType *BspKnotEvalAlphaCoef(int k, CagdRType *KVT,
- int LengthKVT, CagdRType *KVt, int LengthKVt)
- {
- int i, j, o;
- CagdRType *m, **Rows;
- BspKnotAlphaCoeffType
- *A = (BspKnotAlphaCoeffType *)
- IritMalloc(sizeof(BspKnotAlphaCoeffType));
-
- A -> Order = k;
- A -> Length = LengthKVT;
- A -> RefLength = LengthKVt;
- A -> Matrix = (CagdRType *) IritMalloc(sizeof(CagdRType) * (LengthKVT + 1)
- * LengthKVt);
- Rows = A -> Rows = (CagdRType **) IritMalloc(sizeof(CagdRType *) *
- (LengthKVT + 1));
- A -> ColIndex = (int *) IritMalloc(sizeof(int) * LengthKVt);
- A -> ColLength = (int *) IritMalloc(sizeof(int) * LengthKVt);
-
- /* Update the row pointers to point onto the matrix rows. */
- for (i = 0, j = 0; i <= LengthKVT; i++, j += LengthKVt)
- Rows[i] = &A -> Matrix[j];
-
- /* Initialize the matrix with according to order 1: */
- for (m = A -> Matrix, i = (LengthKVT + 1) * LengthKVt; i > 0; i--)
- *m++ = 0.0;
- for (i = 0; i < LengthKVT; i++) {
- CagdRType
- *RowI = Rows[i],
- KVTI = KVT[i],
- KVTI1 = KVT[i + 1];
-
- for (j = 0; j < LengthKVt; j++, RowI++) {
- if (KVTI <= KVt[j] && KVt[j] < KVTI1)
- *RowI = 1.0;
- }
- }
-
- /* Iterate upto order k: */
- for (o = 2; o <= k; o++) {
- for (i = 0; i < LengthKVT; i++) {
- CagdRType
- *RowI = Rows[i],
- *RowI1 = Rows[i + 1],
- KVTI = KVT[i],
- KVTIO = KVT[i + o],
- t1 = KVT[i + o - 1] - KVTI,
- t2 = KVTIO - KVT[i + 1];
-
- /* If ti == 0, the whole term should be ignored. */
- if (t1 < EPSILON)
- t1 = KNOT_INFINITY;
- if (t2 < EPSILON)
- t2 = KNOT_INFINITY;
-
- for (j = 0; j < LengthKVt; j++, RowI++, RowI1++) {
- int jo = j + o;
-
- *RowI = *RowI * (KVt[jo - 1] - KVTI) / t1 +
- *RowI1 * (KVTIO - KVt[jo - 1]) / t2;
- }
- }
- }
-
- /* Update the row non zero indices. */
- for (i = LengthKVt - 1; i >= 0; i--) {
- for (j = 0; j < LengthKVT && APX_EQ(Rows[j][i], 0.0); j++);
- A -> ColIndex[i] = j;
- for (j = LengthKVT - 1; j >= 0 && APX_EQ(Rows[j][i], 0.0); j--);
- if ((A -> ColLength[i] = j + 1 - A -> ColIndex[i]) <= 0)
- FATAL_ERROR(CAGD_ERR_DEGEN_ALPHA);
- }
-
- return A;
- }
-
- /******************************************************************************
- * Same as EvalAlphaCoef but the new knot set NewKV is merged with KVT to *
- * form the new knot vector KVt. *
- ******************************************************************************/
- void BspKnotFreeAlphaCoef(BspKnotAlphaCoeffType *A)
- {
- IritFree((VoidPtr) A -> Matrix);
- IritFree((VoidPtr) A -> Rows);
- IritFree((VoidPtr) A -> ColIndex);
- IritFree((VoidPtr) A -> ColLength);
- IritFree((VoidPtr) A);
- }
-
- /******************************************************************************
- * Same as EvalAlphaCoef but the new knot set NewKV is merged with KVT to *
- * form the new knot vector KVt. *
- ******************************************************************************/
- BspKnotAlphaCoeffType *BspKnotEvalAlphaCoefMerge(int k, CagdRType *KVT,
- int LengthKVT, CagdRType *NewKV, int LengthNewKV)
- {
- int LengthKVt;
- BspKnotAlphaCoeffType *A;
-
- if (NewKV == NULL || LengthNewKV == 0) {
- A = BspKnotEvalAlphaCoef(k, KVT, LengthKVT, KVT, LengthKVT);
- }
- else {
- CagdRType
- *KVt = BspKnotMergeTwo(KVT, LengthKVT + k,
- NewKV, LengthNewKV, 0, &LengthKVt);
-
- A = BspKnotEvalAlphaCoef(k, KVT, LengthKVT, KVt, LengthKVt - k);
-
- IritFree(KVt);
- }
-
- return A;
- }
-
- /******************************************************************************
- * Prepare a refinement vector for the given knot vector domain with n *
- * inserted knots equally spaced. *
- ******************************************************************************/
- CagdRType *BspKnotPrepEquallySpaced(int n, CagdRType Tmin, CagdRType Tmax)
- {
- int i;
- CagdRType dt, t, *RefKV;
-
- if (n <= 0) {
- FATAL_ERROR(CAGD_ERR_WRONG_INDEX);
- return NULL;
- }
-
- dt = (Tmax - Tmin) / (n + 1),
- t = Tmin + dt,
- RefKV = (CagdRType *) IritMalloc(sizeof(CagdRType) * n);
-
- for (i = 0; i < n; i++, t += dt) {
- RefKV[i] = t;
- }
- return RefKV;
- }
-
- #ifdef DEBUG
- /******************************************************************************
- * Prints the content of the alpha matrix. *
- ******************************************************************************/
- static void PrintAlphaMat(BspKnotAlphaCoeffType *A)
- {
- int i, j;
-
- fprintf(stderr, "Order = %d, Length = %d\n", A -> Order, A -> Length);
- for (i = 0; i < A -> Length; i++) {
- for (j = 0; j < A -> RefLength; j++)
- fprintf(stderr, " %9.5lg", A -> Rows[i][j]);
- fprintf(stderr, "\n");
- }
-
- fprintf(stderr, " ");
- for (j = 0; j < A -> RefLength; j++)
- fprintf(stderr, " %3d %3d |", A -> ColIndex[j], A -> ColLength[j]);
- fprintf(stderr, "\n");
- }
- #endif /* DEBUG */
-